package com.rock.app.base;

import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import com.jfinal.aop.Before;
import com.jfinal.core.Controller;
import com.jfinal.core.NotAction;
import com.jfinal.kit.Ret;
import com.jfinal.plugin.activerecord.Model;
import com.rock.app.controller.interceptor.OpenInterceptor;
import com.rock.app.jwt.JwtInterceptor;
import com.rock.app.jwt.JwtManager;
import com.rock.sys.model.TSApp;
import com.rock.sys.model.TSAppRelease;
import com.rock.sys.model.TUser;


@Before({JwtInterceptor.class, OpenInterceptor.class})
public abstract class OpenControllerBase extends Controller {


    private HashMap<String, Object> jwtMap;

    @NotAction
    public Controller setJwtAttr(String name, Object value) {
        if (jwtMap == null) {
            jwtMap = new HashMap<>();
        }

        jwtMap.put(name, value);
        return this;
    }


    @NotAction
    public Controller setJwtMap(Map map) {
        if (map == null) {
            throw new NullPointerException("map is null");
        }
        if (jwtMap == null) {
            jwtMap = new HashMap<>();
        }

        jwtMap.putAll(map);
        return this;
    }


    @NotAction
    public <T> T getJwtAttr(String name) {
        return jwtMap == null ? null : (T) jwtMap.get(name);
    }


    @NotAction
    public HashMap<String, Object> getJwtAttrs() {
        return jwtMap;
    }

    @NotAction
    public <T> T getJwtPara(String name) {
        return JwtManager.me().getPara(name);
    }

    @NotAction
    public Map getJwtParas() {
        return JwtManager.me().getParas();
    }

    @NotAction
    public String createJwtToken() throws Exception {
        if (jwtMap == null) {
            throw new NullPointerException("jwt attrs is null");
        }
        return JwtManager.me().createJwtToken(jwtMap);
    }
    
    protected void renderFailJson(String message) {
        renderJson(Ret.fail("msg", message));
    }

    protected void renderFailJson(int code, String message) {
        renderJson(Ret.fail("code", code).set("msg", message));
    }

    protected void renderOkJson(String attr, Object value) {
        renderJson(Ret.ok(attr, value));
    }
    protected void renderOkDataJson(Object value){
        renderJson(Ret.ok("data", value));
    }

    protected TUser getLoginedUserApi() {
        return getAttr(OpenConsts.ATTR_LOGINED_USER);
    }

    public TSApp getCurrentApp() {
    	TSApp app = getAttr(OpenConsts.ATTR_LOGINED_APP);
    	return app;
    }
    
    protected TSAppRelease getCurrentAppRelease() {
    	TSAppRelease appr = getAttr(OpenConsts.ATTR_LOGINED_APP_RELEASE);
    	return appr;
    }
    

    @NotAction
    public Long getIdPara() {
        Long id = getParaToLong();
        if (id == null) {
            //renderError 会直接抛出异常，阻止程序往下执行
            renderError(404);
        }
        return id;
    }


    protected void render404If(boolean condition) {
        if (condition) {
            renderError(404);
        }
    }


    @Override
    @NotAction
    public String getPara(String name) {
        String value = super.getPara(name);
        return "".equals(value) ? null : value;
    }


    protected boolean notLoginedUserModel(Model model) {
        return !isLoginedUserModel(model, "user_id");
    }

    protected boolean notLoginedUserModel(Model model, String attrName) {
        return !isLoginedUserModel(model, attrName);
    }

    protected boolean isLoginedUserModel(Model model) {
        return isLoginedUserModel(model, "user_id");
    }

    protected boolean isLoginedUserModel(Model model, String attrName) {
        if (model == null) {
            return false;
        }
        Object userId = model.get(attrName);
        if (userId == null) {
            return false;
        }
        TUser loginedUser = getLoginedUser();
        if (loginedUser == null) {
            return false;
        }
        return userId.equals(loginedUser.getId());
    }

    protected TUser getLoginedUser() {
        return getAttr(OpenConsts.ATTR_LOGINED_USER);
    }


    protected static final Ret OK = Ret.ok();
    protected static final Ret FAIL = Ret.fail();
    protected static final Map<Object, Ret> FAIL_RETS = new ConcurrentHashMap<>();

    @NotAction
    protected void renderOkJson() {
        renderJson(OK);
    }

    @NotAction
    protected void renderFailJson() {
        renderJson(FAIL);
    }

    @NotAction
    protected void renderFailJson(Object message) {
        renderFailJson(message, false);
    }

    /**
     * 对于某些高并发的接口，useCache 应该传入 true，减少 ret 的创建
     *
     * @param message
     * @param useCache
     */
    @NotAction
    protected void renderFailJson(Object message, boolean useCache) {
        if (!useCache) {
            renderJson(Ret.fail().set("message", message));
            return;
        }

        Ret ret = FAIL_RETS.get(message);
        if (ret == null) {
            ret = Ret.fail().set("message", message);
            FAIL_RETS.put(message, ret);
        }
        renderJson(ret);
    }
    
    @NotAction
    public Map<String, String> getParas() {
        Map<String, String> map = null;
        Enumeration<String> names = getParaNames();
        if (names != null) {
            map = new HashMap<>();
            while (names.hasMoreElements()) {
                String name = names.nextElement();
                map.put(name, getPara(name));
            }
        }
        return map;
    }
}
